import re

import loguru

import parse_cmake.parsing as cmake_parsing
import os
from ruamel import yaml
from ruamel.yaml.emitter import Emitter
from esdb import search
import yaml_tool
Emitter.MAX_SIMPLE_KEY_LENGTH = 4096


class CmakeDepends:
    def __init__(self):
        self.reflect_lib = {}
        self.save_lib_var_dict = []
        self.lib_var_dict = {}
        self.related_lib_vars = set()
        self.option_condition_map = {}
        self.libraries_dict = {}
        self.related_vars = set()
        self.direct_related = set()
        self.condition = 'buildRequires'
        self.libraries_dict[self.condition] = set()
        self.var_dict = {}
        self.in_if = 0
        self.if_condition = []

        self.need_back = False
        self.lib_var_need_back = False
        self.save_var_dict = []

        self.remove_library = []

        self.option_dict = {}

        self.commands_info = {}

        self.lib_var = set()
        self.lib_var_value = {}

        self.option_condition = {}

        self.target_condition = {}

        self.last_word = []

        self.appear_var = set()

        self.ecm_dict = {'ECMAddQch': ['BUILD_QCH', 'True'], 'ECMCoverageOption': ['BUILD_COVERAGE', 'OFF'],
                         'ECMMarkAsTest': ['BUILD_TESTING', 'ON'], 'ECMQmlModule': ['BUILD_SHARED_LIBS', '']}

        # please record both var and vals, and match both.
        self.match_var = {'ADSP', 'AIX', 'Android', 'ARTOS', 'BeOS', 'BlueGeneL', 'BlueGeneP-dynamic',
                          'BlueGeneP-static', 'BlueGeneQ-dynamic', 'BlueGeneQ-static', 'BSDOS', 'Catamount',
                          'CrayLinuxEnvironment', 'CYGWIN', 'Darwin', 'DOS', 'DragonFly', 'eCos', 'Emscripten', 'Euros',
                          'FreeBSD', 'Fuchsia', 'Generic-ADSP', 'Generic-ELF', 'Generic', 'GHS-MULTI', 'GNU', 'Haiku',
                          'HP-UX', 'iOS', 'kFreeBSD', 'Linux', 'Midipix', 'MirBSD', 'MP-RAS', 'MSYS', 'NetBSD',
                          'OpenBSD', 'OpenVMS', 'OS2', 'OSF1', 'QNX', 'RISCos', 'SCO_SV', 'SerenityOS', 'SINIX',
                          'SunOS', 'syllable', 'Tru64', 'tvOS', 'ULTRIX', 'UNIX_SV', 'UnixWare', 'visionOS', 'watchOS',
                          'Windows', 'WindowsCE', 'WindowsPhone', 'WindowsStore', 'Xenix', 'Debug', 'Release',
                          'RelWithDebInfo', 'MinSizeRel', 'Absoft', 'ADSP', 'AppleClang', 'ARMCC', 'ARMClang', 'Bruce',
                          'CCur', 'Clang', 'Cray', 'CrayClang', 'Embarcadero', 'Borland', 'Flang', 'LLVMFlang',
                          'Fujitsu', 'FujitsuClang', 'G95', 'GNU', 'GHS', 'HP', 'IAR', 'Intel', 'IntelLLVM', 'LCC',
                          'MSVC', 'NVHPC', 'NVIDIA', 'OrangeC', 'OpenWatcom', 'PGI', 'PathScale', 'SDCC', 'SunPro',
                          'Tasking', 'TI', 'TIClang', 'TinyCC', 'XL', 'VisualAge', 'zOS', 'XLClang', 'IBMClang'}

        self.word_operator = {'EQUAL': '=', 'LESS': '<', 'LESS_EQUAL': '<=', 'GREATER': '>', 'GREATER_EQUAL': '>=',
                              'STREQUAL': '=', 'STRLESS': '<', 'STRLESS_EQUAL': '=', 'STRGREATER': '>',
                              'STRGREATER_EQUAL': '>=', 'VERSION_EQUAL': '=', 'VERSION_LESS': '<',
                              'VERSION_LESS_EQUAL': '<=', 'VERSION_GREATER': '>', 'VERSION_GREATER_EQUAL': '>=',
                              'PATH_EQUAL': '='}

        self.find_library_Param = {'NAMES_PER_DIR', 'HINTS', 'PATHS', 'REGISTRY_VIEW', 'PATH_SUFFIXES', 'VALIDATOR',
                                   'DOC', 'NO_CACHE', 'REQUIRED', 'NO_DEFAULT_PATH', 'NO_PACKAGE_ROOT_PATH',
                                   'NO_CMAKE_PATH', 'NO_CMAKE_ENVIRONMENT_PATH', 'NO_SYSTEM_ENVIRONMENT_PATH',
                                   'NO_CMAKE_SYSTEM_PATH', 'NO_CMAKE_INSTALL_PREFIX', 'CMAKE_FIND_ROOT_PATH_BOTH',
                                   'ONLY_CMAKE_FIND_ROOT_PATH', 'NO_CMAKE_FIND_ROOT_PATH'}

        self.find_package_Param = {'EXACT', 'QUIET', 'REQUIRED', 'COMPONENTS', 'OPTIONAL_COMPONENTS',
                                   'CONFIG', 'NO_MODULE', 'GLOBAL', 'NO_POLICY_SCOPE', 'BYPASS_PROVIDER', 'NAMES',
                                   'CONFIGS', 'HINTS', 'PATHS', 'REGISTRY_VIEW', 'PATH_SUFFIXES', 'NO_DEFAULT_PATH',
                                   'NO_PACKAGE_ROOT_PATH', 'NO_CMAKE_PATH', 'NO_CMAKE_ENVIRONMENT_PATH',
                                   'NO_SYSTEM_ENVIRONMENT_PATH', 'NO_CMAKE_PACKAGE_REGISTRY', 'NO_CMAKE_BUILDS_PATH',
                                   'NO_CMAKE_SYSTEM_PATH', 'NO_CMAKE_INSTALL_PREFIX',
                                   'NO_CMAKE_SYSTEM_PACKAGE_REGISTRY', 'CMAKE_FIND_ROOT_PATH_BOTH',
                                   'ONLY_CMAKE_FIND_ROOT_PATH', 'NO_CMAKE_FIND_ROOT_PATH'}

        self.target_link_libraries_Param = {'PRIVATE', 'PUBLIC', 'INTERFACE', 'LINK_PRIVATE', 'LINK_PUBLIC>',
                                            'LINK_INTERFACE_LIBRARIES'}

        self.internal_varname = {'CMAKE_AR', 'CMAKE_ARGC', 'CMAKE_ARGV0', 'CMAKE_BINARY_DIR', 'CMAKE_BUILD_TOOL',
                                 'CMAKE_CACHE_MAJOR_VERSION', 'CMAKE_CACHE_MINOR_VERSION', 'CMAKE_CACHE_PATCH_VERSION',
                                 'CMAKE_CACHEFILE_DIR', 'CMAKE_CFG_INTDIR', 'CMAKE_COMMAND', 'CMAKE_CPACK_COMMAND',
                                 'CMAKE_CROSSCOMPILING', 'CMAKE_CROSSCOMPILING_EMULATOR', 'CMAKE_CTEST_COMMAND',
                                 'CMAKE_CURRENT_BINARY_DIR', 'CMAKE_CURRENT_FUNCTION',
                                 'CMAKE_CURRENT_FUNCTION_LIST_DIR', 'CMAKE_CURRENT_FUNCTION_LIST_FILE',
                                 'CMAKE_CURRENT_FUNCTION_LIST_LINE', 'CMAKE_CURRENT_LIST_DIR',
                                 'CMAKE_CURRENT_LIST_FILE', 'CMAKE_CURRENT_LIST_LIN', 'CMAKE_CURRENT_SOURCE_DIR',
                                 'CMAKE_DEBUG_TARGET_PROPERTIES', 'CMAKE_DIRECTORY_LABELS', 'CMAKE_DL_LIBS',
                                 'CMAKE_DOTNET_SDK', 'CMAKE_DOTNET_TARGET_FRAMEWORK',
                                 'CMAKE_DOTNET_TARGET_FRAMEWORK_VERSION', 'CMAKE_EDIT_COMMAND',
                                 'CMAKE_EXECUTABLE_SUFFIX', 'CMAKE_EXECUTABLE_SUFFIX_CXX', 'CMAKE_EXECUTABLE_SUFFIX_C',
                                 'CMAKE_EXTRA_SHARED_LIBRARY_SUFFIXES', 'CMAKE_FIND_DEBUG_MODE',
                                 'CMAKE_FIND_PACKAGE_NAME', 'CMAKE_FIND_PACKAGE_REDIRECTS_DIR',
                                 'CMAKE_FIND_PACKAGE_SORT_DIRECTION', 'CMAKE_FIND_PACKAGE_SORT_ORDER',
                                 'CMAKE_GENERATOR', 'CMAKE_GENERATOR_INSTANCE', 'CMAKE_GENERATOR_PLATFORM',
                                 'CMAKE_GENERATOR_TOOLSET', 'CMAKE_IMPORT_LIBRARY_PREFIX',
                                 'CMAKE_IMPORT_LIBRARY_SUFFIX', 'CMAKE_JOB_POOL_COMPILE', 'CMAKE_JOB_POOL_LINK',
                                 'CMAKE_JOB_POOL_PRECOMPILE_HEADER', 'CMAKE_JOB_POOLS', 'CMAKE_CXX_COMPILER_AR',
                                 'CMAKE_CXX_COMPILER_FRONTEND_VARIANT', 'CMAKE_CXX_COMPILER_LINKER',
                                 'CMAKE_CXX_COMPILER_LINKER_FRONTEND_VARIANT', 'CMAKE_CXX_COMPILER_LINKER_ID',
                                 'CMAKE_CXX_COMPILER_LINKER_VERSION', 'CMAKE_CXX_COMPILER_RANLIB',
                                 'CMAKE_CXX_LINK_LIBRARY_SUFFIX', 'CMAKE_C_COMPILER_AR',
                                 'CMAKE_C_COMPILER_FRONTEND_VARIANT', 'CMAKE_C_COMPILER_LINKER',
                                 'CMAKE_C_COMPILER_LINKER_FRONTEND_VARIANT', 'CMAKE_C_COMPILER_LINKER_ID',
                                 'CMAKE_C_COMPILER_LINKER_VERSION', 'CMAKE_C_COMPILER_RANLIB',
                                 'CMAKE_C_LINK_LIBRARY_SUFFIX', 'CMAKE_LINK_LIBRARY_SUFFIX',
                                 'CMAKE_LINK_SEARCH_END_STATIC', 'CMAKE_LINK_SEARCH_START_STATIC',
                                 'CMAKE_MAJOR_VERSION', 'CMAKE_MAKE_PROGRAM', 'CMAKE_MATCH_COUNT', 'CMAKE_MATCH_<n>',
                                 'CMAKE_MINIMUM_REQUIRED_VERSION', 'CMAKE_MINOR_VERSION', 'CMAKE_NETRC',
                                 'CMAKE_NETRC_FILE', 'CMAKE_PARENT_LIST_FILE', 'CMAKE_PATCH_VERSION',
                                 'CMAKE_PROJECT_DESCRIPTION', 'CMAKE_PROJECT_HOMEPAGE_URL', 'CMAKE_PROJECT_NAME',
                                 'CMAKE_PROJECT_VERSION', 'CMAKE_PROJECT_VERSION_MAJOR', 'CMAKE_PROJECT_VERSION_MINOR',
                                 'CMAKE_PROJECT_VERSION_PATCH', 'CMAKE_PROJECT_VERSION_TWEAK', 'CMAKE_RANLIB',
                                 'CMAKE_ROOT', 'CMAKE_RULE_MESSAGES', 'CMAKE_SCRIPT_MODE_FILE',
                                 'CMAKE_SHARED_LIBRARY_PREFIX', 'CMAKE_SHARED_LIBRARY_SUFFIX',
                                 'CMAKE_SHARED_MODULE_PREFI', 'CMAKE_SHARED_MODULE_SUFFIX', 'CMAKE_SIZEOF_VOID_P',
                                 'CMAKE_SKIP_INSTALL_RULES', 'CMAKE_SKIP_RPATH', 'CMAKE_SOURCE_DIR',
                                 'CMAKE_STATIC_LIBRARY_PREFIX', 'CMAKE_STATIC_LIBRARY_SUFFIX',
                                 'CMAKE_Swift_COMPILATION_MODE', 'CMAKE_Swift_MODULE_DIRECTORY',
                                 'CMAKE_Swift_NUM_THREADS', 'CMAKE_TEST_LAUNCHER', 'CMAKE_TOOLCHAIN_FILE',
                                 'CMAKE_TWEAK_VERSION', 'CMAKE_VERBOSE_MAKEFILE', 'CMAKE_VERSION',
                                 'CMAKE_VS_DEVENV_COMMAND', 'CMAKE_VS_MSBUILD_COMMAND', 'CMAKE_VS_NsightTegra_VERSION',
                                 'CMAKE_VS_NUGET_PACKAGE_RESTORE', 'CMAKE_VS_PLATFORM_NAME',
                                 'CMAKE_VS_PLATFORM_NAME_DEFAULT', 'CMAKE_VS_PLATFORM_TOOLSET',
                                 'CMAKE_VS_PLATFORM_TOOLSET_CUDA', 'CMAKE_VS_PLATFORM_TOOLSET_CUDA_CUSTOM_DIR',
                                 'CMAKE_VS_PLATFORM_TOOLSET_FORTRAN', 'CMAKE_VS_PLATFORM_TOOLSET_HOST_ARCHITECTURE',
                                 'CMAKE_VS_PLATFORM_TOOLSET_VERSION', 'CMAKE_VS_TARGET_FRAMEWORK_IDENTIFIER',
                                 'CMAKE_VS_TARGET_FRAMEWORK_TARGETS_VERSION', 'CMAKE_VS_TARGET_FRAMEWORK_VERSION',
                                 'CMAKE_VS_VERSION_BUILD_NUMBER', 'CMAKE_VS_WINDOWS_TARGET_PLATFORM_MIN_VERSION',
                                 'CMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION',
                                 'CMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION_MAXIMUM', 'CMAKE_XCODE_BUILD_SYSTEM',
                                 'CMAKE_XCODE_PLATFORM_TOOLSET', 'PROJECT_BINARY_DIR',
                                 'PROJECT_DESCRIPTION', 'PROJECT_HOMEPAGE_URL', 'PROJECT_IS_TOP_LEVEL', 'PROJECT_NAME',
                                 'PROJECT_SOURCE_DIR', 'PROJECT_VERSION', 'PROJECT_VERSION_MAJOR',
                                 'PROJECT_VERSION_MINOR', 'PROJECT_VERSION_PATCH', 'PROJECT_VERSION_TWEAK',
                                 'BUILD_SHARED_LIBS', 'CMAKE_ABSOLUTE_DESTINATION_FILES',
                                 'CMAKE_ADD_CUSTOM_COMMAND_DEPENDS_EXPLICIT_ONLY', 'CMAKE_APPBUNDLE_PATH',
                                 'CMAKE_BUILD_TYPE', 'CMAKE_CLANG_VFS_OVERLAY', 'CMAKE_CODEBLOCKS_COMPILER_ID',
                                 'CMAKE_CODEBLOCKS_EXCLUDE_EXTERNAL_FILES', 'CMAKE_CODELITE_USE_TARGETS',
                                 'CMAKE_COLOR_DIAGNOSTICS', 'CMAKE_COLOR_MAKEFILE', 'CMAKE_CONFIGURATION_TYPES',
                                 'CMAKE_DEPENDS_IN_PROJECT_ONLY', 'CMAKE_DISABLE_FIND_PACKAGE_ < PackageName >',
                                 'CMAKE_ECLIPSE_GENERATE_LINKED_RESOURCES', 'CMAKE_ECLIPSE_GENERATE_SOURCE_PROJECT',
                                 'CMAKE_ECLIPSE_MAKE_ARGUMENTS', 'CMAKE_ECLIPSE_RESOURCE_ENCODING',
                                 'CMAKE_ECLIPSE_VERSION', 'CMAKE_ERROR_DEPRECATED',
                                 'CMAKE_ERROR_ON_ABSOLUTE_INSTALL_DESTINATION', 'CMAKE_EXECUTE_PROCESS_COMMAND_ECHO',
                                 'CMAKE_EXPORT_COMPILE_COMMANDS', 'CMAKE_EXPORT_PACKAGE_REGISTRY',
                                 'CMAKE_EXPORT_NO_PACKAGE_REGISTRY', 'CMAKE_FIND_APPBUNDLE', 'CMAKE_FIND_FRAMEWORK',
                                 'CMAKE_FIND_LIBRARY_CUSTOM_LIB_SUFFIX', 'CMAKE_FIND_LIBRARY_PREFIXES',
                                 'CMAKE_FIND_LIBRARY_SUFFIXES', 'CMAKE_FIND_NO_INSTALL_PREFIX',
                                 'CMAKE_FIND_PACKAGE_PREFER_CONFIG', 'CMAKE_FIND_PACKAGE_RESOLVE_SYMLINKS',
                                 'CMAKE_FIND_PACKAGE_TARGETS_GLOBAL', 'CMAKE_FIND_PACKAGE_WARN_NO_MODULE',
                                 'CMAKE_FIND_ROOT_PATH', 'CMAKE_FIND_ROOT_PATH_MODE_INCLUDE',
                                 'CMAKE_FIND_ROOT_PATH_MODE_LIBRARY', 'CMAKE_FIND_ROOT_PATH_MODE_PACKAGE',
                                 'CMAKE_FIND_ROOT_PATH_MODE_PROGRAM', 'CMAKE_FIND_USE_CMAKE_ENVIRONMENT_PATH',
                                 'CMAKE_FIND_USE_CMAKE_PATH', 'CMAKE_FIND_USE_CMAKE_SYSTEM_PATH',
                                 'CMAKE_FIND_USE_INSTALL_PREFIX', 'CMAKE_FIND_USE_PACKAGE_REGISTRY',
                                 'CMAKE_FIND_USE_PACKAGE_ROOT_PATH', 'CMAKE_FIND_USE_SYSTEM_ENVIRONMENT_PATH',
                                 'CMAKE_FIND_USE_SYSTEM_PACKAGE_REGISTRY', 'CMAKE_FRAMEWORK_PATH', 'CMAKE_IGNORE_PATH',
                                 'CMAKE_IGNORE_PREFIX_PATH', 'CMAKE_INCLUDE_DIRECTORIES_BEFORE',
                                 'CMAKE_INCLUDE_DIRECTORIES_PROJECT_BEFORE', 'CMAKE_INCLUDE_PATH',
                                 'CMAKE_INSTALL_DEFAULT_COMPONENT_NAME', 'CMAKE_INSTALL_DEFAULT_DIRECTORY_PERMISSIONS',
                                 'CMAKE_INSTALL_MESSAGE', 'CMAKE_INSTALL_PREFIX',
                                 'CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT', 'CMAKE_KATE_FILES_MODE',
                                 'CMAKE_KATE_MAKE_ARGUMENTS', 'CMAKE_LIBRARY_PATH', 'CMAKE_LINK_DIRECTORIES_BEFORE',
                                 'CMAKE_LINK_LIBRARIES_ONLY_TARGETS', 'CMAKE_MAXIMUM_RECURSION_DEPTH',
                                 'CMAKE_MESSAGE_CONTEXT', 'CMAKE_MESSAGE_CONTEXT_SHOW', 'CMAKE_MESSAGE_INDENT',
                                 'CMAKE_MESSAGE_LOG_LEVEL', 'CMAKE_MFC_FLAG', 'CMAKE_MODULE_PATH',
                                 'CMAKE_POLICY_DEFAULT_CMP < NNNN >', 'CMAKE_POLICY_WARNING_CMP < NNNN >',
                                 'CMAKE_PREFIX_PATH', 'CMAKE_PROGRAM_PATH', 'CMAKE_PROJECT_INCLUDE',
                                 'CMAKE_PROJECT_INCLUDE_BEFORE', 'CMAKE_PROJECT_ < PROJECT - NAME > _INCLUDE',
                                 'CMAKE_PROJECT_ < PROJECT - NAME > _INCLUDE_BEFORE',
                                 'CMAKE_PROJECT_TOP_LEVEL_INCLUDES', 'CMAKE_REQUIRE_FIND_PACKAGE_ < PackageName >',
                                 'CMAKE_SKIP_INSTALL_ALL_DEPENDENCY', 'CMAKE_SKIP_TEST_ALL_DEPENDENCY',
                                 'CMAKE_STAGING_PREFIX', 'CMAKE_SUBLIME_TEXT_2_ENV_SETTINGS',
                                 'CMAKE_SUBLIME_TEXT_2_EXCLUDE_BUILD_TREE', 'CMAKE_SUPPRESS_REGENERATION',
                                 'CMAKE_SYSROOT', 'CMAKE_SYSROOT_COMPILE', 'CMAKE_SYSROOT_LINK',
                                 'CMAKE_SYSTEM_APPBUNDLE_PATH', 'CMAKE_SYSTEM_FRAMEWORK_PATH',
                                 'CMAKE_SYSTEM_IGNORE_PATH', 'CMAKE_SYSTEM_IGNORE_PREFIX_PATH',
                                 'CMAKE_SYSTEM_INCLUDE_PATH', 'CMAKE_SYSTEM_LIBRARY_PATH', 'CMAKE_SYSTEM_PREFIX_PATH',
                                 'CMAKE_SYSTEM_PROGRAM_PATH', 'CMAKE_TLS_CAINFO', 'CMAKE_TLS_VERIFY',
                                 'CMAKE_USER_MAKE_RULES_OVERRIDE', 'CMAKE_WARN_DEPRECATED',
                                 'CMAKE_WARN_ON_ABSOLUTE_INSTALL_DESTINATION', 'CMAKE_XCODE_GENERATE_SCHEME',
                                 'CMAKE_XCODE_GENERATE_TOP_LEVEL_PROJECT_ONLY', 'CMAKE_XCODE_LINK_BUILD_PHASE_MODE',
                                 'CMAKE_XCODE_SCHEME_ADDRESS_SANITIZER',
                                 'CMAKE_XCODE_SCHEME_ADDRESS_SANITIZER_USE_AFTER_RETURN',
                                 'CMAKE_XCODE_SCHEME_DEBUG_DOCUMENT_VERSIONING',
                                 'CMAKE_XCODE_SCHEME_DISABLE_MAIN_THREAD_CHECKER',
                                 'CMAKE_XCODE_SCHEME_DYNAMIC_LIBRARY_LOADS',
                                 'CMAKE_XCODE_SCHEME_DYNAMIC_LINKER_API_USAGE',
                                 'CMAKE_XCODE_SCHEME_ENABLE_GPU_API_VALIDATION',
                                 'CMAKE_XCODE_SCHEME_ENABLE_GPU_FRAME_CAPTURE_MODE',
                                 'CMAKE_XCODE_SCHEME_ENABLE_GPU_SHADER_VALIDATION', 'CMAKE_XCODE_SCHEME_ENVIRONMENT',
                                 'CMAKE_XCODE_SCHEME_GUARD_MALLOC', 'CMAKE_XCODE_SCHEME_LAUNCH_CONFIGURATION',
                                 'CMAKE_XCODE_SCHEME_LAUNCH_MODE', 'CMAKE_XCODE_SCHEME_MAIN_THREAD_CHECKER_STOP',
                                 'CMAKE_XCODE_SCHEME_MALLOC_GUARD_EDGES', 'CMAKE_XCODE_SCHEME_MALLOC_SCRIBBLE',
                                 'CMAKE_XCODE_SCHEME_MALLOC_STACK', 'CMAKE_XCODE_SCHEME_THREAD_SANITIZER',
                                 'CMAKE_XCODE_SCHEME_THREAD_SANITIZER_STOP',
                                 'CMAKE_XCODE_SCHEME_UNDEFINED_BEHAVIOUR_SANITIZER',
                                 'CMAKE_XCODE_SCHEME_UNDEFINED_BEHAVIOUR_SANITIZER_STOP',
                                 'CMAKE_XCODE_SCHEME_WORKING_DIRECTORY', 'CMAKE_XCODE_SCHEME_ZOMBIE_OBJECTS',
                                 'CMAKE_XCODE_XCCONFIG', '< PackageName > _ROOT', 'ANDROID', 'APPLE', 'BORLAND', 'BSD',
                                 'CMAKE_ANDROID_NDK_VERSION', 'CMAKE_CL_64', 'CMAKE_COMPILER_2005', 'CMAKE_HOST_APPLE',
                                 'CMAKE_HOST_BSD', 'CMAKE_HOST_LINUX', 'CMAKE_HOST_SOLARIS', 'CMAKE_HOST_SYSTEM',
                                 'CMAKE_HOST_SYSTEM_NAME', 'CMAKE_HOST_SYSTEM_PROCESSOR', 'CMAKE_HOST_SYSTEM_VERSION',
                                 'CMAKE_HOST_UNIX', 'CMAKE_HOST_WIN32', 'CMAKE_LIBRARY_ARCHITECTURE',
                                 'CMAKE_LIBRARY_ARCHITECTURE_REGEX', 'CMAKE_OBJECT_PATH_MAX', 'CMAKE_SYSTEM',
                                 'CMAKE_SYSTEM_NAME', 'CMAKE_SYSTEM_PROCESSOR', 'CMAKE_SYSTEM_VERSION', 'CYGWIN',
                                 'GHSMULTI', 'IOS', 'LINUX', 'MINGW', 'MSVC', 'MSVC_IDE', 'MSVC_TOOLSET_VERSION',
                                 'MSVC_VERSION', 'MSYS', 'UNIX', 'WIN32', 'WINCE', 'WINDOWS_PHONE', 'WINDOWS_STORE',
                                 'XCODE', 'XCODE_VERSION', 'CMAKE_ADSP_ROOT', 'CMAKE_AIX_EXPORT_ALL_SYMBOLS',
                                 'CMAKE_ANDROID_ANT_ADDITIONAL_OPTIONS', 'CMAKE_ANDROID_API', 'CMAKE_ANDROID_API_MIN',
                                 'CMAKE_ANDROID_ARCH', 'CMAKE_ANDROID_ARCH_ABI', 'CMAKE_ANDROID_ARM_MODE',
                                 'CMAKE_ANDROID_ARM_NEON', 'CMAKE_ANDROID_ASSETS_DIRECTORIES',
                                 'CMAKE_ANDROID_EXCEPTIONS', 'CMAKE_ANDROID_GUI', 'CMAKE_ANDROID_JAR_DEPENDENCIES',
                                 'CMAKE_ANDROID_JAR_DIRECTORIES', 'CMAKE_ANDROID_JAVA_SOURCE_DIR',
                                 'CMAKE_ANDROID_NATIVE_LIB_DEPENDENCIES', 'CMAKE_ANDROID_NATIVE_LIB_DIRECTORIES',
                                 'CMAKE_ANDROID_NDK', 'CMAKE_ANDROID_NDK_DEPRECATED_HEADERS',
                                 'CMAKE_ANDROID_NDK_TOOLCHAIN_HOST_TAG', 'CMAKE_ANDROID_NDK_TOOLCHAIN_VERSION',
                                 'CMAKE_ANDROID_PROCESS_MAX', 'CMAKE_ANDROID_PROGUARD',
                                 'CMAKE_ANDROID_PROGUARD_CONFIG_PATH', 'CMAKE_ANDROID_RTTI',
                                 'CMAKE_ANDROID_SECURE_PROPS_PATH', 'CMAKE_ANDROID_SKIP_ANT_STEP',
                                 'CMAKE_ANDROID_STANDALONE_TOOLCHAIN', 'CMAKE_ANDROID_STL_TYPE',
                                 'CMAKE_APPLE_SILICON_PROCESSOR', 'CMAKE_ARCHIVE_OUTPUT_DIRECTORY',
                                 'CMAKE_ARCHIVE_OUTPUT_DIRECTORY_ < CONFIG >',
                                 'CMAKE_AUTOGEN_BETTER_GRAPH_MULTI_CONFIG', 'CMAKE_AUTOGEN_COMMAND_LINE_LENGTH_MAX',
                                 'CMAKE_AUTOGEN_ORIGIN_DEPENDS', 'CMAKE_AUTOGEN_PARALLEL',
                                 'CMAKE_AUTOGEN_USE_SYSTEM_INCLUDE', 'CMAKE_AUTOGEN_VERBOSE', 'CMAKE_AUTOMOC',
                                 'CMAKE_AUTOMOC_COMPILER_PREDEFINES', 'CMAKE_AUTOMOC_DEPEND_FILTERS',
                                 'CMAKE_AUTOMOC_MACRO_NAMES', 'CMAKE_AUTOMOC_MOC_OPTIONS', 'CMAKE_AUTOMOC_PATH_PREFIX',
                                 'CMAKE_AUTOMOC_EXECUTABLE', 'CMAKE_AUTORCC', 'CMAKE_AUTORCC_OPTIONS',
                                 'CMAKE_AUTORCC_EXECUTABLE', 'CMAKE_AUTOUIC', 'CMAKE_AUTOUIC_OPTIONS',
                                 'CMAKE_AUTOUIC_SEARCH_PATHS', 'CMAKE_AUTOUIC_EXECUTABLE', 'CMAKE_BUILD_RPATH',
                                 'CMAKE_BUILD_RPATH_USE_ORIGIN', 'CMAKE_BUILD_WITH_INSTALL_NAME_DIR',
                                 'CMAKE_BUILD_WITH_INSTALL_RPATH', 'CMAKE_COMPILE_PDB_OUTPUT_DIRECTORY',
                                 'CMAKE_COMPILE_PDB_OUTPUT_DIRECTORY_ < CONFIG >', 'CMAKE_COMPILE_WARNING_AS_ERROR',
                                 'CMAKE_ < CONFIG > _POSTFIX', 'CMAKE_CROSS_CONFIGS', 'CMAKE_CTEST_ARGUMENTS',
                                 'CMAKE_CUDA_RESOLVE_DEVICE_SYMBOLS', 'CMAKE_CUDA_RUNTIME_LIBRARY',
                                 'CMAKE_CUDA_SEPARABLE_COMPILATION', 'CMAKE_CXX_SCAN_FOR_MODULES',
                                 'CMAKE_DEBUG_POSTFIX', 'CMAKE_DEFAULT_BUILD_TYPE', 'CMAKE_DEFAULT_CONFIGS',
                                 'CMAKE_DEPENDS_USE_COMPILER', 'CMAKE_DISABLE_PRECOMPILE_HEADERS',
                                 'CMAKE_DLL_NAME_WITH_SOVERSION', 'CMAKE_ENABLE_EXPORTS',
                                 'CMAKE_EXECUTABLE_ENABLE_EXPORTS', 'CMAKE_EXE_LINKER_FLAGS',
                                 'CMAKE_EXE_LINKER_FLAGS_ < CONFIG >', 'CMAKE_EXE_LINKER_FLAGS_ < CONFIG > _INIT',
                                 'CMAKE_EXE_LINKER_FLAGS_INIT', 'CMAKE_EXPORT_FIND_PACKAGE_NAME', 'CMAKE_FOLDER',
                                 'CMAKE_Fortran_FORMAT', 'CMAKE_Fortran_MODULE_DIRECTORY', 'CMAKE_Fortran_PREPROCESS',
                                 'CMAKE_FRAMEWORK', 'CMAKE_FRAMEWORK_MULTI_CONFIG_POSTFIX_ < CONFIG >',
                                 'CMAKE_GHS_NO_SOURCE_GROUP_FILE', 'CMAKE_GLOBAL_AUTOGEN_TARGET',
                                 'CMAKE_GLOBAL_AUTOGEN_TARGET_NAME', 'CMAKE_GLOBAL_AUTORCC_TARGET',
                                 'CMAKE_GLOBAL_AUTORCC_TARGET_NAME', 'CMAKE_GNUtoMS', 'CMAKE_INCLUDE_CURRENT_DIR',
                                 'CMAKE_INCLUDE_CURRENT_DIR_IN_INTERFACE', 'CMAKE_INSTALL_NAME_DIR',
                                 'CMAKE_INSTALL_REMOVE_ENVIRONMENT_RPATH', 'CMAKE_INSTALL_RPATH',
                                 'CMAKE_INSTALL_RPATH_USE_LINK_PATH', 'CMAKE_INTERPROCEDURAL_OPTIMIZATION',
                                 'CMAKE_INTERPROCEDURAL_OPTIMIZATION_ < CONFIG >', 'CMAKE_CXX_CLANG_TIDY',
                                 'CMAKE_CXX_CLANG_TIDY_EXPORT_FIXES_DIR', 'CMAKE_CXX_COMPILER_LAUNCHER',
                                 'CMAKE_CXX_CPPCHECK', 'CMAKE_CXX_CPPLINT',
                                 'CMAKE_CXX_INCLUDE_WHAT_YOU_USE',
                                 'CMAKE_CXX_LINK_GROUP_USING_ < FEATURE >',
                                 'CMAKE_CXX_LINK_GROUP_USING_ < FEATURE > _SUPPORTED',
                                 'CMAKE_CXX_LINK_LIBRARY_FILE_FLAG', 'CMAKE_CXX_LINK_LIBRARY_FLAG',
                                 'CMAKE_CXX_LINK_LIBRARY_USING_ < FEATURE >',
                                 'CMAKE_CXX_LINK_LIBRARY_USING_ < FEATURE > _SUPPORTED',
                                 'CMAKE_CXX_LINK_WHAT_YOU_USE_FLAG', 'CMAKE_CXX_LINKER_LAUNCHER',
                                 'CMAKE_CXX_USING_LINKER_MODE', 'CMAKE_CXX_USING_LINKER_ < TYPE >',
                                 'CMAKE_CXX_VISIBILITY_PRESET', 'CMAKE_C_CLANG_TIDY',
                                 'CMAKE_C_CLANG_TIDY_EXPORT_FIXES_DIR', 'CMAKE_C_COMPILER_LAUNCHER',
                                 'CMAKE_C_CPPCHECK', 'CMAKE_C_CPPLINT',
                                 'CMAKE_C_INCLUDE_WHAT_YOU_USE',
                                 'CMAKE_C_LINK_GROUP_USING_ < FEATURE >',
                                 'CMAKE_C_LINK_GROUP_USING_ < FEATURE > _SUPPORTED',
                                 'CMAKE_C_LINK_LIBRARY_FILE_FLAG', 'CMAKE_C_LINK_LIBRARY_FLAG',
                                 'CMAKE_C_LINK_LIBRARY_USING_ < FEATURE >',
                                 'CMAKE_C_LINK_LIBRARY_USING_ < FEATURE > _SUPPORTED',
                                 'CMAKE_C_LINK_WHAT_YOU_USE_FLAG', 'CMAKE_C_LINKER_LAUNCHER',
                                 'CMAKE_C_USING_LINKER_MODE', 'CMAKE_C_USING_LINKER_ < TYPE >',
                                 'CMAKE_C_VISIBILITY_PRESET', 'CMAKE_LIBRARY_OUTPUT_DIRECTORY',
                                 'CMAKE_LIBRARY_OUTPUT_DIRECTORY_ < CONFIG >', 'CMAKE_LIBRARY_PATH_FLAG',
                                 'CMAKE_LINK_DEF_FILE_FLAG', 'CMAKE_LINK_DEPENDS_NO_SHARED',
                                 'CMAKE_LINK_DEPENDS_USE_LINKER', 'CMAKE_LINK_GROUP_USING_ < FEATURE >',
                                 'CMAKE_LINK_GROUP_USING_ < FEATURE > _SUPPORTED', 'CMAKE_LINK_INTERFACE_LIBRARIES',
                                 'CMAKE_LINK_LIBRARY_FILE_FLAG', 'CMAKE_LINK_LIBRARY_FLAG',
                                 'CMAKE_LINK_LIBRARY_USING_ < FEATURE >',
                                 'CMAKE_LINK_LIBRARY_USING_ < FEATURE > _SUPPORTED', 'CMAKE_LINK_WHAT_YOU_USE',
                                 'CMAKE_LINK_WHAT_YOU_USE_CHECK', 'CMAKE_LINKER_TYPE', 'CMAKE_MACOSX_BUNDLE',
                                 'CMAKE_MACOSX_RPATH', 'CMAKE_MAP_IMPORTED_CONFIG_ < CONFIG >',
                                 'CMAKE_MODULE_LINKER_FLAGS', 'CMAKE_MODULE_LINKER_FLAGS_ < CONFIG >',
                                 'CMAKE_MODULE_LINKER_FLAGS_ < CONFIG > _INIT', 'CMAKE_MODULE_LINKER_FLAGS_INIT',
                                 'CMAKE_MSVC_DEBUG_INFORMATION_FORMAT', 'CMAKE_MSVC_RUNTIME_LIBRARY',
                                 'CMAKE_MSVCIDE_RUN_PATH', 'CMAKE_NINJA_OUTPUT_PATH_PREFIX', 'CMAKE_NO_BUILTIN_CHRPATH',
                                 'CMAKE_NO_SYSTEM_FROM_IMPORTED', 'CMAKE_OPTIMIZE_DEPENDENCIES',
                                 'CMAKE_OSX_ARCHITECTURES', 'CMAKE_OSX_DEPLOYMENT_TARGET', 'CMAKE_OSX_SYSROOT',
                                 'CMAKE_PCH_INSTANTIATE_TEMPLATES', 'CMAKE_PCH_WARN_INVALID',
                                 'CMAKE_PDB_OUTPUT_DIRECTORY', 'CMAKE_PDB_OUTPUT_DIRECTORY_ < CONFIG >',
                                 'CMAKE_PLATFORM_NO_VERSIONED_SONAME', 'CMAKE_POSITION_INDEPENDENT_CODE',
                                 'CMAKE_RUNTIME_OUTPUT_DIRECTORY', 'CMAKE_RUNTIME_OUTPUT_DIRECTORY_ < CONFIG >',
                                 'CMAKE_SHARED_LIBRARY_ENABLE_EXPORTS', 'CMAKE_SHARED_LINKER_FLAGS',
                                 'CMAKE_SHARED_LINKER_FLAGS_ < CONFIG >', 'CMAKE_SHARED_LINKER_FLAGS_ < CONFIG > _INIT',
                                 'CMAKE_SHARED_LINKER_FLAGS_INIT', 'CMAKE_SKIP_BUILD_RPATH', 'CMAKE_SKIP_INSTALL_RPATH',
                                 'CMAKE_STATIC_LINKER_FLAGS', 'CMAKE_STATIC_LINKER_FLAGS_ < CONFIG >',
                                 'CMAKE_STATIC_LINKER_FLAGS_ < CONFIG > _INIT', 'CMAKE_STATIC_LINKER_FLAGS_INIT',
                                 'CMAKE_TASKING_TOOLSET', 'CMAKE_TRY_COMPILE_CONFIGURATION',
                                 'CMAKE_TRY_COMPILE_NO_PLATFORM_VARIABLES', 'CMAKE_TRY_COMPILE_PLATFORM_VARIABLES',
                                 'CMAKE_TRY_COMPILE_TARGET_TYPE', 'CMAKE_UNITY_BUILD', 'CMAKE_UNITY_BUILD_BATCH_SIZE',
                                 'CMAKE_UNITY_BUILD_UNIQUE_ID', 'CMAKE_VERIFY_INTERFACE_HEADER_SETS',
                                 'CMAKE_VISIBILITY_INLINES_HIDDEN', 'CMAKE_VS_DEBUGGER_COMMAND',
                                 'CMAKE_VS_DEBUGGER_COMMAND_ARGUMENTS', 'CMAKE_VS_DEBUGGER_ENVIRONMENT',
                                 'CMAKE_VS_DEBUGGER_WORKING_DIRECTORY', 'CMAKE_VS_GLOBALS',
                                 'CMAKE_VS_INCLUDE_INSTALL_TO_DEFAULT_BUILD',
                                 'CMAKE_VS_INCLUDE_PACKAGE_TO_DEFAULT_BUILD', 'CMAKE_VS_JUST_MY_CODE_DEBUGGING',
                                 'CMAKE_VS_NO_COMPILE_BATCHING', 'CMAKE_VS_SDK_EXCLUDE_DIRECTORIES',
                                 'CMAKE_VS_SDK_EXECUTABLE_DIRECTORIES', 'CMAKE_VS_SDK_INCLUDE_DIRECTORIES',
                                 'CMAKE_VS_SDK_LIBRARY_DIRECTORIES', 'CMAKE_VS_SDK_LIBRARY_WINRT_DIRECTORIES',
                                 'CMAKE_VS_SDK_REFERENCE_DIRECTORIES', 'CMAKE_VS_SDK_SOURCE_DIRECTORIES',
                                 'CMAKE_VS_WINRT_BY_DEFAULT', 'CMAKE_WATCOM_RUNTIME_LIBRARY', 'CMAKE_WIN32_EXECUTABLE',
                                 'CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS', 'CMAKE_XCODE_ATTRIBUTE_ < an - attribute >',
                                 'EXECUTABLE_OUTPUT_PATH', 'LIBRARY_OUTPUT_PATH', 'CMAKE_C_COMPILE_FEATURES',
                                 'CMAKE_C_EXTENSIONS', 'CMAKE_C_STANDARD', 'CMAKE_C_STANDARD_REQUIRED',
                                 'CMAKE_CUDA_ARCHITECTURES', 'CMAKE_CUDA_COMPILE_FEATURES', 'CMAKE_CUDA_EXTENSIONS',
                                 'CMAKE_CUDA_HOST_COMPILER', 'CMAKE_CUDA_STANDARD', 'CMAKE_CUDA_STANDARD_REQUIRED',
                                 'CMAKE_CUDA_TOOLKIT_INCLUDE_DIRECTORIES', 'CMAKE_CXX_COMPILE_FEATURES',
                                 'CMAKE_CXX_EXTENSIONS', 'CMAKE_CXX_STANDARD', 'CMAKE_CXX_STANDARD_REQUIRED',
                                 'CMAKE_Fortran_MODDIR_DEFAULT', 'CMAKE_Fortran_MODDIR_FLAG',
                                 'CMAKE_Fortran_MODOUT_FLAG', 'CMAKE_HIP_ARCHITECTURES', 'CMAKE_HIP_EXTENSIONS',
                                 'CMAKE_HIP_PLATFORM', 'CMAKE_HIP_STANDARD', 'CMAKE_HIP_STANDARD_REQUIRED',
                                 'CMAKE_ISPC_HEADER_DIRECTORY', 'CMAKE_ISPC_HEADER_SUFFIX',
                                 'CMAKE_ISPC_INSTRUCTION_SETS', 'CMAKE_CXX_ANDROID_TOOLCHAIN_MACHINE',
                                 'CMAKE_CXX_ANDROID_TOOLCHAIN_PREFIX',
                                 'CMAKE_CXX_ANDROID_TOOLCHAIN_SUFFIX', 'CMAKE_CXX_ARCHIVE_APPEND',
                                 'CMAKE_CXX_ARCHIVE_CREATE', 'CMAKE_CXX_ARCHIVE_FINISH',
                                 'CMAKE_CXX_BYTE_ORDER', 'CMAKE_CXX_COMPILE_OBJECT',
                                 'CMAKE_CXX_COMPILER', 'CMAKE_CXX_COMPILER_EXTERNAL_TOOLCHAIN',
                                 'CMAKE_CXX_COMPILER_ID', 'CMAKE_CXX_COMPILER_LOADED',
                                 'CMAKE_CXX_COMPILER_PREDEFINES_COMMAND', 'CMAKE_CXX_COMPILER_TARGET',
                                 'CMAKE_CXX_COMPILER_VERSION', 'CMAKE_CXX_CREATE_SHARED_LIBRARY',
                                 'CMAKE_CXX_CREATE_SHARED_MODULE', 'CMAKE_CXX_CREATE_STATIC_LIBRARY',
                                 'CMAKE_CXX_EXTENSIONS', 'CMAKE_CXX_EXTENSIONS_DEFAULT',
                                 'CMAKE_CXX_FLAGS', 'CMAKE_CXX_FLAGS_ < CONFIG >',
                                 'CMAKE_CXX_FLAGS_ < CONFIG > _INIT', 'CMAKE_CXX_FLAGS_DEBUG',
                                 'CMAKE_CXX_FLAGS_DEBUG_INIT', 'CMAKE_CXX_FLAGS_INIT',
                                 'CMAKE_CXX_FLAGS_MINSIZEREL', 'CMAKE_CXX_FLAGS_MINSIZEREL_INIT',
                                 'CMAKE_CXX_FLAGS_RELEASE', 'CMAKE_CXX_FLAGS_RELEASE_INIT',
                                 'CMAKE_CXX_FLAGS_RELWITHDEBINFO', 'CMAKE_CXX_FLAGS_RELWITHDEBINFO_INIT',
                                 'CMAKE_CXX_HOST_COMPILER', 'CMAKE_CXX_IGNORE_EXTENSIONS',
                                 'CMAKE_CXX_IMPLICIT_INCLUDE_DIRECTORIES',
                                 'CMAKE_CXX_IMPLICIT_LINK_DIRECTORIES',
                                 'CMAKE_CXX_IMPLICIT_LINK_FRAMEWORK_DIRECTORIES',
                                 'CMAKE_CXX_IMPLICIT_LINK_LIBRARIES', 'CMAKE_CXX_LIBRARY_ARCHITECTURE',
                                 'CMAKE_CXX_LINK_EXECUTABLE', 'CMAKE_CXX_LINKER_WRAPPER_FLAG',
                                 'CMAKE_CXX_LINKER_WRAPPER_FLAG_SEP', 'CMAKE_CXX_OUTPUT_EXTENSION',
                                 'CMAKE_CXX_SIMULATE_ID', 'CMAKE_CXX_SIMULATE_VERSION',
                                 'CMAKE_CXX_SIZEOF_DATA_PTR', 'CMAKE_CXX_SOURCE_FILE_EXTENSIONS',
                                 'CMAKE_CXX_STANDARD', 'CMAKE_CXX_STANDARD_DEFAULT',
                                 'CMAKE_CXX_STANDARD_INCLUDE_DIRECTORIES', 'CMAKE_CXX_STANDARD_LIBRARIES',
                                 'CMAKE_CXX_STANDARD_REQUIRED', 'CMAKE_C_FLAGS_DEBUG',
                                 'CMAKE_C_FLAGS_DEBUG_INIT', 'CMAKE_C_FLAGS_INIT',
                                 'CMAKE_C_FLAGS_MINSIZEREL', 'CMAKE_C_FLAGS_MINSIZEREL_INIT',
                                 'CMAKE_C_FLAGS_RELEASE', 'CMAKE_C_FLAGS_RELEASE_INIT',
                                 'CMAKE_C_FLAGS_RELWITHDEBINFO', 'CMAKE_C_FLAGS_RELWITHDEBINFO_INIT',
                                 'CMAKE_C_HOST_COMPILER', 'CMAKE_C_IGNORE_EXTENSIONS',
                                 'CMAKE_C_IMPLICIT_INCLUDE_DIRECTORIES',
                                 'CMAKE_C_IMPLICIT_LINK_DIRECTORIES',
                                 'CMAKE_C_IMPLICIT_LINK_FRAMEWORK_DIRECTORIES',
                                 'CMAKE_C_IMPLICIT_LINK_LIBRARIES', 'CMAKE_C_LIBRARY_ARCHITECTURE',
                                 'CMAKE_C_LINK_EXECUTABLE', 'CMAKE_C_LINKER_WRAPPER_FLAG',
                                 'CMAKE_C_LINKER_WRAPPER_FLAG_SEP', 'CMAKE_C_OUTPUT_EXTENSION',
                                 'CMAKE_C_SIMULATE_ID', 'CMAKE_C_SIMULATE_VERSION',
                                 'CMAKE_C_SIZEOF_DATA_PTR', 'CMAKE_C_SOURCE_FILE_EXTENSIONS',
                                 'CMAKE_C_STANDARD', 'CMAKE_C_STANDARD_DEFAULT',
                                 'CMAKE_C_STANDARD_INCLUDE_DIRECTORIES', 'CMAKE_C_STANDARD_LIBRARIES',
                                 'CMAKE_C_STANDARD_REQUIRED', 'CMAKE_OBJC_EXTENSIONS', 'CMAKE_OBJC_STANDARD',
                                 'CMAKE_OBJC_STANDARD_REQUIRED', 'CMAKE_OBJCXX_EXTENSIONS', 'CMAKE_OBJCXX_STANDARD',
                                 'CMAKE_OBJCXX_STANDARD_REQUIRED', 'CMAKE_Swift_LANGUAGE_VERSION',
                                 'CMAKE_USER_MAKE_RULES_OVERRIDE_CXX', 'CMAKE_USER_MAKE_RULES_OVERRIDE_C',
                                 'CTEST_BINARY_DIRECTORY',
                                 'CTEST_BUILD_COMMAND', 'CTEST_BUILD_NAME', 'CTEST_BZR_COMMAND',
                                 'CTEST_BZR_UPDATE_OPTIONS', 'CTEST_CHANGE_ID', 'CTEST_CHECKOUT_COMMAND',
                                 'CTEST_CONFIGURATION_TYPE', 'CTEST_CONFIGURE_COMMAND', 'CTEST_COVERAGE_COMMAND',
                                 'CTEST_COVERAGE_EXTRA_FLAGS', 'CTEST_CURL_OPTIONS', 'CTEST_CUSTOM_COVERAGE_EXCLUDE',
                                 'CTEST_CUSTOM_ERROR_EXCEPTION', 'CTEST_CUSTOM_ERROR_MATCH',
                                 'CTEST_CUSTOM_ERROR_POST_CONTEXT', 'CTEST_CUSTOM_ERROR_PRE_CONTEXT',
                                 'CTEST_CUSTOM_MAXIMUM_FAILED_TEST_OUTPUT_SIZE',
                                 'CTEST_CUSTOM_MAXIMUM_NUMBER_OF_ERRORS', 'CTEST_CUSTOM_MAXIMUM_NUMBER_OF_WARNINGS',
                                 'CTEST_CUSTOM_MAXIMUM_PASSED_TEST_OUTPUT_SIZE', 'CTEST_CUSTOM_MEMCHECK_IGNORE',
                                 'CTEST_CUSTOM_POST_MEMCHECK', 'CTEST_CUSTOM_POST_TEST', 'CTEST_CUSTOM_PRE_MEMCHECK',
                                 'CTEST_CUSTOM_PRE_TEST', 'CTEST_CUSTOM_TEST_OUTPUT_TRUNCATION',
                                 'CTEST_CUSTOM_TESTS_IGNORE', 'CTEST_CUSTOM_WARNING_EXCEPTION',
                                 'CTEST_CUSTOM_WARNING_MATCH', 'CTEST_CVS_COMMAND', 'CTEST_CVS_UPDATE_OPTIONS',
                                 'CTEST_DROP_LOCATION', 'CTEST_DROP_METHOD', 'CTEST_DROP_SITE', 'CTEST_DROP_SITE_CDASH',
                                 'CTEST_DROP_SITE_PASSWORD', 'CTEST_DROP_SITE_USER', 'CTEST_EXTRA_COVERAGE_GLOB',
                                 'CTEST_GIT_COMMAND', 'CTEST_GIT_INIT_SUBMODULES', 'CTEST_GIT_UPDATE_CUSTOM',
                                 'CTEST_GIT_UPDATE_OPTIONS', 'CTEST_HG_COMMAND', 'CTEST_HG_UPDATE_OPTIONS',
                                 'CTEST_LABELS_FOR_SUBPROJECTS', 'CTEST_MEMORYCHECK_COMMAND',
                                 'CTEST_MEMORYCHECK_COMMAND_OPTIONS', 'CTEST_MEMORYCHECK_SANITIZER_OPTIONS',
                                 'CTEST_MEMORYCHECK_SUPPRESSIONS_FILE', 'CTEST_MEMORYCHECK_TYPE',
                                 'CTEST_NIGHTLY_START_TIME', 'CTEST_P4_CLIENT', 'CTEST_P4_COMMAND', 'CTEST_P4_OPTIONS',
                                 'CTEST_P4_UPDATE_OPTIONS', 'CTEST_RESOURCE_SPEC_FILE', 'CTEST_RUN_CURRENT_SCRIPT',
                                 'CTEST_SCRIPT_DIRECTORY', 'CTEST_SITE', 'CTEST_SOURCE_DIRECTORY',
                                 'CTEST_SUBMIT_INACTIVITY_TIMEOUT', 'CTEST_SUBMIT_URL', 'CTEST_SVN_COMMAND',
                                 'CTEST_SVN_OPTIONS', 'CTEST_SVN_UPDATE_OPTIONS', 'CTEST_TEST_LOAD',
                                 'CTEST_TEST_TIMEOUT', 'CTEST_UPDATE_COMMAND', 'CTEST_UPDATE_OPTIONS',
                                 'CTEST_UPDATE_VERSION_ONLY', 'CTEST_UPDATE_VERSION_OVERRIDE', 'CTEST_USE_LAUNCHERS',
                                 'CPACK_ABSOLUTE_DESTINATION_FILES', 'CPACK_COMPONENT_INCLUDE_TOPLEVEL_DIRECTORY',
                                 'CPACK_CUSTOM_INSTALL_VARIABLES', 'CPACK_ERROR_ON_ABSOLUTE_INSTALL_DESTINATION',
                                 'CPACK_INCLUDE_TOPLEVEL_DIRECTORY', 'CPACK_INSTALL_DEFAULT_DIRECTORY_PERMISSIONS',
                                 'CPACK_PACKAGING_INSTALL_PREFIX', 'CPACK_SET_DESTDIR',
                                 'CPACK_WARN_ON_ABSOLUTE_INSTALL_DESTINATION', 'CACHE', 'ENV', 'CMAKE_HOME_DIRECTORY',
                                 'CMAKE_INTERNAL_PLATFORM_ABI', 'CMAKE_CXX_COMPILER_ABI',
                                 'CMAKE_CXX_COMPILER_ARCHITECTURE_ID',
                                 'CMAKE_CXX_COMPILER_VERSION_INTERNAL', 'CMAKE_CXX_LINKER_PREFERENCE',
                                 'CMAKE_CXX_LINKER_PREFERENCE_PROPAGATES', 'CMAKE_CXX_PLATFORM_ID',
                                 'CMAKE_C_COMPILER_ABI',
                                 'CMAKE_C_COMPILER_ARCHITECTURE_ID',
                                 'CMAKE_C_COMPILER_VERSION_INTERNAL', 'CMAKE_C_LINKER_PREFERENCE',
                                 'CMAKE_C_LINKER_PREFERENCE_PROPAGATES', 'CMAKE_C_PLATFORM_ID',
                                 'CMAKE_NOT_USING_CONFIG_FLAGS', 'CMAKE_VS_INTEL_Fortran_PROJECT_VERSION',
                                 'CMAKE_EXTRA_GENERATOR', 'CMAKE_AUTOMOC_RELAXED_MODE', 'CMAKE_BACKWARDS_COMPATIBILITY',
                                 'CMAKE_FIND_PACKAGE_NO_PACKAGE_REGISTRY',
                                 'CMAKE_FIND_PACKAGE_NO_SYSTEM_PACKAGE_REGISTRY', 'MSVC10', 'MSVC11', 'MSVC12',
                                 'MSVC14', 'MSVC60', 'MSVC70', 'MSVC71', 'MSVC80', 'MSVC90',
                                 'CMAKE_IOS_INSTALL_COMBINED', 'CMAKE_USE_RELATIVE_PATHS', 'CMAKE_COMPILER_IS_GNUCC',
                                 'CMAKE_COMPILER_IS_GNUCXX', 'CMAKE_COMPILER_IS_GNUG77', 'CTEST_CVS_CHECKOUT',
                                 'CTEST_SCP_COMMAND', 'CTEST_TRIGGER_SITE'}
        self.project_name_var = {'_BINARY_DIR', '_DESCRIPTION', '_HOMEPAGE_URL', '_IS_TOP_LEVEL', '_SOURCE_DIR',
                                 '_VERSION', '_VERSION_MAJOR', '_VERSION_MINOR', '_VERSION_PATCH', '_VERSION_TWEAK', }

    def convert_string(self, arg):
        if arg.startswith('"'):
            return arg[1:-1]
        try:
            return int(arg)
        except ValueError:
            try:
                return float(arg)
            except ValueError:
                return arg

    def parse(self, path):
        loguru.logger.info(f"Analysing {path}")
        if not os.path.isfile(path):
            return
        parsed = self.filterCommand(path)
        parsed = self.merge_include_file(path, parsed)
        self.related_var(parsed)
        for token in parsed:
            # print(token)
            if token.name.lower() == 'set':
                if len(token.body) > 1 and token.body[1].contents == 'HINTS':
                    continue
                self.appear_var.add(token.body[0].contents)
                if len(token.body) > 1:
                    if ' when ' in self.condition:
                        a, b = self.option_set(token.body[1].contents)
                        if a:
                            c = self.option_condition.setdefault(token.body[0].contents, {}).setdefault(b, [])
                            if self.condition not in c:
                                c.append(self.condition)

                    # if token.body[0].contents in self.lib_var:
                    #     self.lib_var_value.setdefault(token.body[0].contents, {})[self.condition] = self.convert_string(
                    #         token.body[1].contents)
                if token.body[0].contents in self.related_lib_vars:
                    self.set_lib_var_command(token.body)
                if token.body[0].contents in self.related_vars:
                    self.set_command(token.body)
                elif 'CACHE' in [arg.contents for arg in token.body]:
                    self.set_option(token.body)
            elif token.name.lower() == 'target_link_libraries':
                self.target_command(token.body)
            elif token.name.lower() == 'option' or token.name.lower() == 'set_option':
                self.appear_var.add(token.body[0].contents)
                self.option_command(token.body)
            elif token.name.lower() == 'find_package':
                self.find_package_command(token.body)
            elif 'find_' in token.name.lower() and '_package' in token.name.lower():
                if token.name.lower() == 'find_ksdk_package':
                    self.find_xxx_package_command(token.body)
            elif token.name.lower() == 'set_package_properties':
                self.set_package_properties_command(token.body)
            elif token.name.lower() == 'find_library':
                self.find_library_command(token.body)
            elif token.name.lower() == 'find_program':
                self.find_program_command(token.body)
            elif token.name.lower() == 'find_path':
                self.find_path_command(token.body)
            elif token.name.lower() == 'find_file':
                self.find_file_command(token.body)
            elif token.name.lower() == 'check_include_file':
                self.check_include_file_command(token.body)
            elif token.name.lower() == 'check_include_files':
                self.check_include_files_command(token.body)
            elif token.name.lower() == 'pkg_check_modules':
                self.pkg_check_modules_command(token.body)
            elif token.name.lower() == 'pkg_search_module':
                self.pkg_search_module_command(token.body)
            elif token.name.lower() == 'add_library':
                self.add_library_command(token.body)
            elif token.name.lower() == 'add_executable':
                self.add_executable_command(token.body)
            elif token.name.lower() == 'add_custom_target':
                self.add_custom_target_command(token.body)
            elif token.name.lower() == 'if':
                self.if_command(token.body)
            elif token.name.lower() == 'elseif':
                self.need_back = True
                self.lib_var_need_back = True
                self.elseif_command(token.body)
            elif token.name.lower() == 'else':
                self.need_back = True
                self.lib_var_need_back = True
                self.else_command(token.body)
            elif token.name.lower() == 'endif':
                self.endif_command(token.body)
            elif token.name.lower() == 'add_subdirectory':
                self.subdirectory_command(path, token.body)
            elif token.name.lower() == 'project':
                self.project_command(token.body)
            elif token.name.lower() == 'include':
                self.include_command(token.body)
        self.remove_duplicates_library()

    def include_command(self, arg):
        arg = arg[0].contents
        if arg in self.ecm_dict:
            this_dict = {
                'default_value': self.ecm_dict[arg][1]
            }
            if len(self.condition) > 13:
                this_dict['condition'] = self.condition[14:]
            self.option_dict.setdefault('ECM.' + self.ecm_dict[arg][0], []).append(this_dict)

    def option_set(self, arg):
        true_option = {'1', 'ON', 'YES', 'TRUE', 'Y', 'True'}
        false_option = {'0', 'OFF', 'NO', 'FALSE', 'N', 'IGNORE', 'NOTFOUND', "''", '""', 'False'}

        if not isinstance(arg, str):
            return False, False
        if arg in true_option or re.match(r'^\d+(\.\d+)?$', arg):
            return True, True
        if arg in false_option or arg.endswith('-NOTFOUND'):
            return True, False
        return False, False

    def project_command(self, args):
        project_name = args[0].contents
        for var in self.project_name_var:
            self.internal_varname.add(project_name + var)

    def set_package_properties_command(self, args):
        libname = 'set_package_properties.' + self.var_regulate(args[0].contents)
        info = ' '.join([arg.contents for arg in args[1:]])
        condition = 'requires'
        if len(self.condition) > 13:
            condition += self.condition[14:]
        self.condition_merge(self.condition, {libname})
        this_dict = {
            'name': libname
        }
        if info:
            this_dict['extra_param'] = info
        if len(self.condition) > 13:
            this_dict['condition'] = self.condition[14:]
        self.restore_command_info(libname, this_dict)

    def add_executable_command(self, args):
        a = self.target_condition.setdefault(args[0].contents, [])
        if self.condition not in a:
            a.append(self.condition)

    def add_custom_target_command(self, args):
        a = self.target_condition.setdefault(args[0].contents, [])
        if self.condition not in a:
            a.append(self.condition)

    def add_library_command(self, args):
        a = self.target_condition.setdefault(args[0].contents, [])
        if self.condition not in a:
            a.append(self.condition)
        self.remove_library.append(args[0].contents)

    def restore_command_info(self, libname, this_dict):
        if libname in self.commands_info:
            for every_dict in self.commands_info[libname]:
                if every_dict == this_dict:
                    return
        self.commands_info.setdefault(libname, []).append(this_dict)

    def find_library_command(self, args):
        if len(args) < 2:
            return
        a = 2
        this_lib = []
        if args[1].contents == 'NAMES' or args[1].contents == 'NAME':
            this_lib.append('find_library.' + args[2].contents)
            a = 3
            for arg in args[3:]:
                if arg.contents not in self.find_library_Param:
                    this_lib.append('find_library.' + arg.contents)
                else:
                    break
                a += 1
        else:
            this_lib.append('find_library.' + args[1].contents)
        self.condition_merge(self.condition, set(this_lib))

        info = ''
        while a < len(args):
            info = info + ' ' + args[a].contents
            a += 1

        info = info[1:] if info != '' else info
        for lib in this_lib:
            libname = lib
            this_dict = {
                'name': lib
            }
            if info:
                this_dict['extra_param'] = info
            if len(self.condition) > 13:
                this_dict['condition'] = self.condition[14:]
            self.restore_command_info(libname, this_dict)

    def find_program_command(self, args):
        if len(args) < 2:
            return
        a = 2
        this_lib = []
        if args[1].contents == 'NAMES' or args[1].contents == 'NAME':
            this_lib.append('find_program.' + args[2].contents)
            a = 3
            for arg in args[3:]:
                if arg.contents not in self.find_library_Param:
                    this_lib.append('find_program.' + arg.contents)
                else:
                    break
                a += 1
        else:

            this_lib.append('find_program.' + args[1].contents)
        # print(this_lib)
        self.condition_merge(self.condition, set(this_lib))

        info = ''
        while a < len(args):
            info = info + ' ' + args[a].contents
            a += 1

        info = info[1:] if info != '' else info
        for lib in this_lib:
            libname = lib
            this_dict = {
                'name': lib
            }
            if info:
                this_dict['extra_param'] = info
            if len(self.condition) > 13:
                this_dict['condition'] = self.condition[14:]
            self.restore_command_info(libname, this_dict)

    def find_path_command(self, args):
        a = 2
        this_lib = []
        if args[1].contents == 'NAMES' or args[1].contents == 'NAME':
            this_lib.append('find_path.' + args[2].contents)
            a = 3
            for arg in args[3:]:
                if arg.contents not in self.find_library_Param:
                    this_lib.append('find_path.' + arg.contents)
                else:
                    break
                a += 1
        else:
            this_lib.append('find_path.' + args[1].contents)
        self.condition_merge(self.condition, set(this_lib))

        info = ''
        while a < len(args):
            info = info + ' ' + args[a].contents
            a += 1

        info = info[1:] if info != '' else info
        for lib in this_lib:
            libname = lib
            this_dict = {
                'name': lib
            }
            if info:
                this_dict['extra_param'] = info
            if len(self.condition) > 13:
                this_dict['condition'] = self.condition[14:]
            self.restore_command_info(libname, this_dict)

    def find_file_command(self, args):
        a = 2
        this_lib = []
        if args[1].contents == 'NAMES' or args[1].contents == 'NAME':
            this_lib.append('find_file.' + args[2].contents)
            a = 3
            for arg in args[3:]:
                if arg.contents not in self.find_library_Param:
                    this_lib.append('find_file.' + arg.contents)
                else:
                    break
                a += 1
        else:
            this_lib.append('find_file.' + args[1].contents)
        self.condition_merge(self.condition, set(this_lib))

        info = ''
        while a < len(args):
            info = info + ' ' + args[a].contents
            a += 1

        info = info[1:] if info != '' else info
        for lib in this_lib:
            libname = lib
            this_dict = {
                'name': lib
            }
            if info:
                this_dict['extra_param'] = info
            if len(self.condition) > 13:
                this_dict['condition'] = self.condition[14:]
            self.restore_command_info(libname, this_dict)

    def check_include_file_command(self, args):
        this_lib = []
        operators = ['>=', '<=', '>', '=', '<']
        lib = args[0].contents
        this_lib.append('check_include_file.' + lib)
        self.condition_merge(self.condition, set(this_lib))

        for lib in this_lib:
            libname = lib
            this_dict = {
                'name': lib
            }

            if len(self.condition) > 13:
                this_dict['condition'] = self.condition[14:]
            self.restore_command_info(libname, this_dict)

    def check_include_files_command(self, args):
        this_lib = []
        operators = ['>=', '<=', '>', '=', '<']
        lib = args[0].contents
        this_lib.append('check_include_files.' + lib)
        self.condition_merge(self.condition, set(this_lib))

        for lib in this_lib:
            libname = lib
            this_dict = {
                'name': lib
            }

            if len(self.condition) > 13:
                this_dict['condition'] = self.condition[14:]
            self.restore_command_info(libname, this_dict)

    def pkg_check_modules_command(self, args):
        this_lib = []
        operators = ['>=', '<=', '>', '=', '<']
        info = ''
        for arg in args[1:]:
            if arg.contents in {'REQUIRED', 'QUIET', 'NO_CMAKE_PATH', 'NO_CMAKE_ENVIRONMENT_PATH', 'IMPORTED_TARGET',
                                'GLOBAL'}:
                info += ' ' + arg.contents
                continue
            lib = arg.contents
            for op in operators:
                if op in lib:
                    lib = lib.replace(op, ' ' + op + ' ')
                    break
            this_lib.append('pkg_check_modules.' + lib)
        self.condition_merge(self.condition, set(this_lib))

        info = info[1:] if info != '' else info
        for lib in this_lib:
            libname = lib
            this_dict = {
                'name': lib
            }
            if info:
                this_dict['extra_param'] = info
            if len(self.condition) > 13:
                this_dict['condition'] = self.condition[14:]
            self.restore_command_info(libname, this_dict)

    def pkg_search_module_command(self, args):
        this_lib = []
        operators = ['>=', '<=', '>', '=', '<']
        info = ''
        for arg in args[1:]:
            if arg.contents in {'REQUIRED', 'QUIET', 'NO_CMAKE_PATH', 'NO_CMAKE_ENVIRONMENT_PATH', 'IMPORTED_TARGET',
                                'GLOBAL'}:
                info += ' ' + arg.contents
                continue
            lib = arg.contents
            for op in operators:
                if op in lib:
                    lib = lib.replace(op, ' ' + op + ' ')
                    break
            this_lib.append('pkg_search_module.' + lib)
        self.condition_merge(self.condition, set(this_lib))

        info = info[1:] if info != '' else info
        for lib in this_lib:
            libname = lib
            this_dict = {
                'name': lib
            }
            if info:
                this_dict['extra_param'] = info
            if len(self.condition) > 13:
                this_dict['condition'] = self.condition[14:]
            self.restore_command_info(libname, this_dict)

    def var_regulate(self, arg):
        new_arg = re.sub(r'\$\{(\w+)}', r'${{pkg.var.\1}}', arg)
        return new_arg

    def find_package_command(self, args):
        this_lib = self.var_regulate(args[0].contents)
        version = ''
        if len(args) > 1:
            if re.match(r'^\d+', args[1].contents):
                version = ' = ' + args[1].contents
        libname = 'find_package.' + this_lib
        info = ''
        component_libs = []
        in_component = False
        for arg in args[1:]:
            if in_component:
                if arg.contents in self.find_package_Param:
                    in_component = False
                else:
                    component_libs.append(self.var_regulate(arg.contents))
            info += ' ' + arg.contents
            if arg.contents == 'COMPONENTS':
                in_component = True

        if component_libs:
            libs = {libname + '::' + lib + version for lib in component_libs}
        else:
            libs = {libname + version}

        if 'REQUIRED' in info:
            condition = self.condition
        else:
            condition = 'buildRecommends' + self.condition[13:]
        self.condition_merge(condition, libs)

        info = info[1:] if info != '' else info
        this_dict = {
            'name': libname
        }
        if info:
            this_dict['extra_param'] = info
        if len(self.condition) > 13:
            this_dict['condition'] = self.condition[14:]
        self.restore_command_info(libname, this_dict)

    def find_xxx_package_command(self, args):
        if len(args) < 2:
            return
        this_lib = self.var_regulate(args[1].contents)
        version = ''
        if len(args) > 2:
            if re.match(r'^\d+', args[2].contents):
                version = ' = ' + args[2].contents
        libname = 'find_package.' + this_lib
        print(libname)
        info = ''
        component_libs = []
        in_component = False
        for arg in args[2:]:
            if in_component:
                if arg.contents in self.find_package_Param:
                    in_component = False
                else:
                    component_libs.append(self.var_regulate(arg.contents))
            info += ' ' + arg.contents
            if arg.contents == 'COMPONENTS':
                in_component = True

        if component_libs:
            libs = {libname + '::' + lib + version for lib in component_libs}
        else:
            libs = {libname + version}

        if 'REQUIRED' in info:
            condition = self.condition
        else:
            condition = 'buildRecommends' + self.condition[13:]
        self.condition_merge(condition, libs)

        info = info[1:] if info != '' else info
        this_dict = {
            'name': libname
        }
        if info:
            this_dict['extra_param'] = info
        if len(self.condition) > 13:
            this_dict['condition'] = self.condition[14:]
        self.restore_command_info(libname, this_dict)

    def option_command(self, args):
        option_name = args[0].contents
        help_text = args[1].contents[1:-1].replace('\n', '')
        default_value = args[2].contents if len(args) > 2 else 'OFF'
        if default_value.startswith('${'):
            if default_value[2:-1] in self.lib_var_dict:
                default_value = list(self.lib_var_dict[default_value[2:-1]])[0]
        elif default_value.startswith('"${'):
            if default_value[3:-2] in self.lib_var_dict:
                default_value = list(self.lib_var_dict[default_value[3:-2]])[0]
        if ' when ' in self.condition:
            a, b = self.option_set(default_value)
            if a:
                c = self.option_condition.setdefault(option_name, {}).setdefault(b, [])
                if self.condition not in c:
                    c.append(self.condition)
        this_dict = {
            'help_text': help_text,
            'default_value': default_value
        }
        if len(self.condition) > 13:
            this_dict['condition'] = self.condition[14:]
        self.option_dict.setdefault('option.' + option_name, []).append(this_dict)

    def option_condition_process(self, condition):
        if condition in self.option_condition_map:
            return self.option_condition_map[condition]
        cons = condition.split(' when ')
        result_key = cons[0]
        result_con = []
        # 对于每个when条件后
        for con in cons[1:]:
            sym = True if con[0] == '+' else False
            con = con[2:-1] if con[1] == '(' else con[1:]
            con = re.split(r'( and | or )', con, flags=re.IGNORECASE)
            this_con = ''
            for i in range(0, len(con), 2):
                if con[i].lower().startswith('not'):
                    con_sym = not sym
                    con_con = con[i][4:]
                else:
                    con_sym = sym
                    con_con = con[i]

                if this_con:
                    if (sym and len(con[i - 1]) == 5) or (not sym and len(con[i - 1]) == 4):
                        this_con += ' and '
                    else:
                        this_con += ' or '

                if not con_sym:
                    this_con += 'not '
                this_con += con_con
            if ' or ' in this_con:
                this_con = '(' + this_con + ')'
            result_con.append(this_con)
        if result_con:
            result_key = result_key + ' when ' + ' and '.join(result_con)
        if ' PROCESSOR_COUNT ' in result_key:
            result_key = ''
        self.option_condition_map[condition] = result_key
        return result_key

    def remove_brackets(self, s):
        stack = []
        result = []

        for char in s:
            if char == '(':
                stack.append(len(result))
            elif char == ')' and stack:
                start = stack.pop()
                result = result[:start]

            elif not stack:
                result.append(char)

        return ''.join(result)

    def condition_process(self, condition, condition_symbol=True, repeat_word=None):
        if repeat_word is None:
            repeat_word = set()
        cons = condition.split(' when ')
        result_key = cons[0]
        result_con = []
        result_lib = []
        # 对于每个when条件后
        for con in cons[1:]:
            sym = True if con[0] == '+' else False
            if not condition_symbol:
                sym = not sym
            con = con[2:-1] if con[1] == '(' else con[1:]
            con = re.split(r'( and | or )', con, flags=re.IGNORECASE)
            this_con = ''
            this_lib = ''
            # 每个AND/OR分割后
            for i in range(0, len(con), 2):
                if con[i].lower().startswith('not'):
                    con_sym = not sym
                    con_con = con[i][4:]
                else:
                    con_sym = sym
                    con_con = con[i]

                if con_con.endswith('_FOUND'):
                    if this_lib:
                        if (sym and len(con[i - 1]) == 5) or (not sym and len(con[i - 1]) == 4):
                            this_lib += ' && '
                        else:
                            this_lib += ' || '

                    lib = 'find_package.' + con_con[:-6]
                    if not con_sym:
                        lib = '!' + lib
                    this_lib += lib

                elif con_con.startswith('TARGET') and con_con[7:] in self.target_condition:
                    if con_con[7:] in repeat_word:
                        continue
                    repeat_word.add(con_con[7:])
                    _, b, c = self.condition_process(self.target_condition[con_con[7:]][0], con_sym, repeat_word)
                    if b:
                        no_or = True
                        if this_con:
                            if (sym and len(con[i - 1]) == 5) or (not sym and len(con[i - 1]) == 4):
                                this_con += ' and '
                            else:
                                this_con += ' or '
                                no_or = False

                        if no_or or (len(b) == 1 and ' and ' not in b[0] and ' or ' not in b[0]):
                            this_con += ' and '.join(b)
                        else:
                            this_con += '(' + ' and '.join(b) + ')'

                    if c:
                        if this_lib:
                            if (sym and len(con[i - 1]) == 5) or (not sym and len(con[i - 1]) == 4):
                                this_lib += ' && '
                            else:
                                this_lib += ' || '

                        if not con_sym:
                            this_lib += '!'

                        if len(c) == 1 and ' ' not in c[0]:
                            this_lib += c[0]
                        else:
                            this_lib += '(' + ' && '.join(c) + ')'

                elif ' ' not in con_con and con_con in self.option_condition and True in self.option_condition[con_con]:
                    # print(repeat_word)
                    # print(self.option_condition)
                    if con_con in repeat_word:
                        continue
                    repeat_word.add(con_con)
                    _, b, c = self.condition_process(self.option_condition[con_con][True][0], con_sym, repeat_word)
                    if b:
                        no_or = True
                        if this_con:
                            if (sym and len(con[i - 1]) == 5) or (not sym and len(con[i - 1]) == 4):
                                this_con += ' and '
                            else:
                                this_con += ' or '
                                no_or = False

                        if no_or or (len(b) == 1 and ' and ' not in b[0] and ' or ' not in b[0]):
                            this_con += ' and '.join(b)
                        else:
                            this_con += '(' + ' and '.join(b) + ')'

                    if c:
                        if this_lib:
                            if (sym and len(con[i - 1]) == 5) or (not sym and len(con[i - 1]) == 4):
                                this_lib += ' && '
                            else:
                                this_lib += ' || '

                        if not con_sym:
                            this_lib += '!'

                        if len(c) == 1 and ' ' not in c[0]:
                            this_lib += c[0]
                        else:
                            this_lib += '(' + ' && '.join(c) + ')'

                elif ' MATCHES ' in con_con:
                    if this_con:
                        if (sym and len(con[i - 1]) == 5) or (not sym and len(con[i - 1]) == 4):
                            this_con += ' and '
                        else:
                            this_con += ' or '

                    con_words = con_con.split(' ')
                    match_word = con_words[-1][1:-1] if con_words[-1].startswith('"') else con_words[-1]
                    if match_word in self.match_var:
                        this_con += con_words[0]
                        if con_sym:
                            this_con += ' = ' + con_words[-1]
                        else:
                            this_con += ' != ' + con_words[-1]
                    else:
                        if con_sym:
                            this_con += con_words[0] + ' =~ ' + con_words[-1]
                        else:
                            this_con += '!(' + con_words[0] + ' =~ ' + con_words[-1] + ')'

                else:
                    if this_con:
                        if (sym and len(con[i - 1]) == 5) or (not sym and len(con[i - 1]) == 4):
                            this_con += ' and '
                        else:
                            this_con += ' or '

                    if ' ' in con_con:
                        if con_sym:
                            this_con += con_con
                        else:
                            this_con += '!(' + con_con + ')'
                    else:
                        if con_sym:
                            this_con += '+' + con_con
                        else:
                            this_con += '-' + con_con
            if this_con and this_con not in result_con:
                if ' or ' in self.remove_brackets(this_con):
                    this_con = '(' + this_con + ')'
                result_con.append(this_con)
            if this_lib:
                if ' || ' in this_lib:
                    this_lib = '(' + this_lib + ')'
                if this_lib not in result_lib:
                    result_lib.append(this_lib)
        return result_key, result_con, result_lib

    def merge_same_lib(self, arg):
        if ' || ' in arg:
            return arg
        arg = re.sub(r'[()]', '', arg)
        arg_list = arg.split(' && ')
        return ' && '.join(set(arg_list))

    def condition_merge(self, key, value):
        if len(self.libraries_dict) > 0:
            lib_dict = self.libraries_dict.get('buildRequires')
            if lib_dict is not None:
                value -= lib_dict
        result_key, result_con, result_lib = self.condition_process(key)
        if result_con:
            result_key += ' when ' + ' and '.join(result_con)
        if result_lib:
            result_lib = ' && '.join(result_lib) + ' && '
            result_lib = re.sub(r'!!', '', result_lib)
        self.libraries_dict.setdefault(result_key, set()).update(
            {self.merge_same_lib(result_lib + lib) if result_lib else lib for lib in value})

    def never_appear(self, key):
        matches = re.findall(r'\$\{([^{}]*)}', key)
        for var_name in matches:
            if var_name not in self.appear_var:
                return True
        return False

    def remove_duplicates_library(self):
        remove_set = None
        if 'buildRequires' in self.libraries_dict.keys():
            remove_set = self.libraries_dict['buildRequires'].copy()
        delete_key = set() if remove_set else {'buildRequires'}
        for key, value in self.libraries_dict.items():
            if not value:
                delete_key.add(key)
                continue

            if self.never_appear(key):
                delete_key.add(key)
                continue

            if len(key) > 13 and key.startswith('buildRequires'):
                if remove_set:
                    value -= remove_set
                if not value:
                    delete_key.add(key)
        for key in delete_key:
            if key in self.libraries_dict:
                self.libraries_dict.pop(key)

    def subdirectory_command(self, path, args):
        for arg in args:
            newpath = os.path.normpath(path[:path.rfind(os.sep)] + os.sep + arg.contents) + os.sep + 'CMakeLists.txt'
            self.parse(newpath)

    def word_regulate(self, arg):
        arg = re.sub(r'"\$\{(\w+)}"', r'\1', arg)
        arg = re.sub(r'\$\{(\w+_FOUND)}', r'\1', arg)
        arg = arg[1:-1] if arg[0] == '"' and arg[-1] == '"' else arg

        if arg.startswith('${'):
            if arg[2:-1] in self.internal_varname:
                self.last_word.append(True)
                return 'cmake.' + arg[2:-1]
            elif arg[2:-1].endswith('_VERSION'):
                self.last_word.append(True)
                arg = 'pkg.' + arg[2:-9].lower() + '.version'
                return arg
        else:
            length = len(self.last_word)
            if length > 1:
                if self.last_word[length - 1] == False and self.last_word[length - 2] == True:
                    self.last_word.append('')
                    return "'" + arg + "'"

        if arg in self.internal_varname:
            return 'cmake.' + arg
        else:
            if arg.endswith('_VERSION_MAJOR'):
                self.last_word.append(True)
                return 'pkg.var.' + arg
            elif arg.endswith('_VERSION'):
                self.last_word.append(True)
                return 'pkg.' + arg[:-8].lower() + '.version'
            elif arg in self.word_operator:
                self.last_word.append(False)
                return self.word_operator[arg]
            self.last_word.append('')
            return arg

    def if_command(self, args):
        self.last_word.clear()
        self.if_condition.append([])
        self.in_if += 1
        self.condition += " when"
        if len(args) == 1:
            self.condition += ' +' + self.word_regulate(args[0].contents)
        else:
            self.condition += ' +(' + self.word_regulate(args[0].contents)
            for arg in args[1:]:
                self.condition += ' ' + self.word_regulate(arg.contents)
            self.condition += ')'
        self.save_var_dict.append(self.var_dict.copy())
        self.save_lib_var_dict.append(self.lib_var_dict.copy())

    def elseif_command(self, args):
        self.last_word.clear()
        self.if_condition[-1].append(self.condition[self.condition.rfind(' when') + 5:])
        self.condition = self.condition[:self.condition.rfind(' when') + 5]
        if len(args) == 1:
            self.condition += ' +' + self.word_regulate(args[0].contents)
        else:
            if len(args) > 1:
                self.condition += ' +(' + self.word_regulate(args[0].contents)
            for arg in args[1:]:
                self.condition += ' ' + self.word_regulate(arg.contents)
            self.condition += ')'

    def else_command(self, args):
        self.if_condition[-1].append(self.condition[self.condition.rfind(' when') + 5:])
        self.condition = self.condition[:self.condition.rfind(' when') + 5]
        else_condition = self.if_condition[-1]
        for i in range(len(else_condition)):
            self.condition += ' -' + else_condition[i][2:]
            if i != len(else_condition) - 1:
                self.condition += ' AND'

    def endif_command(self, args):
        self.in_if -= 1
        self.if_condition.pop()
        self.condition = self.condition[:self.condition.rfind(' when')]
        self.var_dict = self.save_var_dict.pop()
        self.lib_var_dict = self.save_lib_var_dict.pop()
        self.need_back = False
        self.lib_var_need_back = False

    def replace_varInLib(self, match):
        key = match.group(1)  # 获取匹配的键
        return self.var_dict.get(key, match.group(0))

    def varLib2actualLib(self, lib):
        if '${' not in lib:
            return lib
        return re.sub(r'\$\{([^}]+)}', self.replace_varInLib, lib)

    def target_command(self, args):
        libs = set()
        for arg in args[1:]:
            if arg.contents in self.target_link_libraries_Param:
                continue
            if arg.contents.startswith('$'):
                var_libs = self.var_dict.get(arg.contents[2:-1], set())
                self.condition_merge(self.condition, var_libs)
                libs.update(var_libs)
            else:
                if arg.contents.startswith('"-l'):
                    lname = arg.contents[3:-1]
                    if lname in self.remove_library:
                        continue
                    lib = 'target_link_libraries.' + self.var_regulate(lname)
                elif arg.contents.startswith('-') or arg.contents.startswith('"-'):
                    continue
                else:
                    lname = arg.contents
                    if lname in self.remove_library:
                        continue
                    lib = 'target_link_libraries.' + self.var_regulate(lname)
                self.condition_merge(self.condition, {lib})
                libs.add(lib)

        for lib in libs:
            if self.condition != 'buildRequires' and self.libraries_dict.get(
                    'buildRequires') is not None and lib in self.libraries_dict.get('buildRequires'):
                continue
            libname = lib
            this_dict = {
                'name': lib
            }
            if len(self.condition) > 13:
                this_dict['condition'] = self.condition[14:]
            self.restore_command_info(libname, this_dict)

    def type_convert(self, arg):
        if arg == 'PATH':
            return 'dir'
        elif arg == 'FILEPATH':
            return 'file'
        return arg.lower()

    def set_option(self, args):
        if args[-1].contents.lower() == 'force':
            return
        var_name = args[0].contents
        default_value = ''
        after_cache = 1
        for arg in args[1:]:
            after_cache += 1
            if arg.contents == 'CACHE':
                break
            default_value += arg.contents + ' '
        if default_value:
            if default_value[0] == '"':
                default_value = default_value[1:-2]
            else:
                default_value = default_value[:-1]

        args = args[after_cache:]
        # this_dict = {
        #     'type': self.type_convert(args[0].contents),
        #     'doc': args[1].contents[1:-1],
        #     'default_value': default_value
        # }
        this_dict = {
            'type': None,
            'doc': None,
            'default_value': default_value
        }
        if len(args) >= 1:
            this_dict['type'] = self.type_convert(args[0].contents)
        if len(args) >= 2:
            this_dict['doc'] = args[1].contents[1:-1]
        if this_dict['type'] == 'string':
            this_dict['default_value'] = re.sub('" "', ' ', default_value)
        if len(self.condition) > 13:
            this_dict['condition'] = self.condition[14:]
        self.option_dict.setdefault('set.' + var_name, []).append(this_dict)

    def set_lib_var_command(self, args):
        if self.lib_var_need_back:
            self.lib_var_dict = self.save_lib_var_dict[-1].copy()
            self.lib_var_need_back = False
        var_name = args[0].contents
        var_value = set()
        for arg in args[1:]:
            if arg.contents.startswith('$'):
                var_value.update(self.lib_var_dict.get(arg.contents[2:-1], set()))
            else:
                var_value.add(arg.contents)
        self.lib_var_dict[var_name] = var_value
        self.lib_var_value.setdefault(var_name, {}).setdefault(self.condition, set()).update(var_value)

    def set_command(self, args):
        if self.need_back:
            self.var_dict = self.save_var_dict[-1].copy()
            self.need_back = False
        var_name = args[0].contents
        var_value = set()
        for arg in args[1:]:
            if arg.contents == 'CACHE':
                self.set_option(args)
                break
            if arg.contents.startswith('$'):
                var_value.update(self.var_dict.get(arg.contents[2:-1], set()))
            else:
                if arg.contents.startswith('"-l'):
                    lname = arg.contents[3:-1]
                    if lname in self.remove_library:
                        continue
                    lib = 'target_link_libraries.' + lname
                elif arg.contents.startswith('-') or arg.contents.startswith('"-'):
                    continue
                else:
                    lname = arg.contents
                    if lname in self.remove_library:
                        continue
                    lib = 'target_link_libraries.' + lname
                var_value.add(lib)
        self.var_dict[var_name] = var_value
        self.condition_merge(self.condition, var_value)

        for lib in var_value:
            if self.condition != 'buildRequires' and self.libraries_dict.get(
                    'buildRequires') is not None and lib in self.libraries_dict.get('buildRequires'):
                continue
            libname = lib
            this_dict = {
                'name': lib
            }
            if len(self.condition) > 13:
                this_dict['condition'] = self.condition[14:]
            self.restore_command_info(libname, this_dict)

    def related_var(self, allCommand):
        target_command = []
        command_nams = {'find_package', 'pkg_check_modules', 'set_package_properties', 'target_link_libraries',
                        'find_library', 'find_program', 'find_path', 'find_file', 'option', 'set_option'}
        for ele in allCommand:
            if ele.name.lower() == 'target_link_libraries':
                target_command.append(ele)
            if ele.name.lower() in command_nams:
                allcontents = ''
                for arg in ele.body:
                    allcontents += arg.contents
                matches = re.findall(r'\${([A-Za-z0-9_]+)}', allcontents)
                if matches:
                    self.lib_var.update(matches)

        for command in target_command:
            for arg in command.body:
                if arg.contents.startswith('$'):
                    self.direct_related.add(arg.contents[2:-1])

        self.related_vars = self.direct_related.copy()
        self.related_lib_vars = self.lib_var.copy()

        all_set_command = [ele for ele in allCommand if ele.name.lower() == 'set']
        self.all_related_vars(all_set_command, self.related_vars)
        for lib_v in self.related_lib_vars:
            self.reflect_lib[lib_v] = lib_v
        # print(self.related_lib_vars)
        self.all_related_vars(all_set_command, self.related_lib_vars, True)

    def all_related_vars(self, all_set_command, vars, reflect=False):
        set_command = [ele for ele in all_set_command if ele.body[0].contents in vars]

        sym = True
        new_related = set()
        while sym:
            sym = False
            for command in set_command:
                for arg in command.body[1:]:
                    if arg.contents.startswith('$'):
                        this_name = arg.contents[2:-1]
                        if this_name not in vars:
                            if reflect:
                                key = command.body[0].contents
                                if key in self.reflect_lib.keys():
                                    self.reflect_lib[this_name] = self.reflect_lib[key]
                            vars.add(this_name)
                            new_related.add(this_name)
                            sym = True
            if sym:
                set_command = [ele for ele in all_set_command if ele.body[0].contents in new_related]
                new_related = set()

    def filterCommand(self, path):
        with open(path, encoding='utf-8') as cmakefile:
            content = cmakefile.read()
            # 检查和移除 BOM
            # 移除 BOM
            if content.startswith('\ufeff'):
                content = content[1:]  # 移除 BOM

            content = content.replace("\\\n", "")
            pattern = re.compile(r"#\[=*\[.*?#]=*]", re.DOTALL | re.MULTILINE)
            content = re.sub(pattern, '', content)

            # 去除新的注释块
            new_comment_pattern = re.compile(r"#\[\[.*?]]", re.DOTALL | re.MULTILINE)
            content = re.sub(new_comment_pattern, '', content)
            # 正则表达式匹配以 @ 开头和结尾的块(单行)
            remove_pattern = re.compile(r"^@.*@$", re.MULTILINE)
            content = re.sub(remove_pattern, '', content)

            # content = re.sub(r'"\$\{(\w+)}"', r'\1', content)

        parsed = cmake_parsing.parse(content)
        parsed = [ele for ele in parsed if type(ele).__name__.endswith('Command')]
        return parsed

    def merge_include_file(self, path, allCommand):
        addIndex = -1
        addCommand = []
        for index, command in enumerate(allCommand):
            if command.name == 'include':
                for arg in command.body:
                    newpath = os.path.normpath(path[:path.rfind(os.sep)] + os.sep + arg.contents)
                    if os.path.isfile(newpath) and '.cmake' in newpath:
                        # 需要是.cmake才能继续解析
                        addIndex = index
                        addCommand.extend(self.merge_include_file(newpath, self.filterCommand(newpath)))
                if addIndex != -1:
                    break
        if addIndex != -1:
            allCommand[addIndex:addIndex + 1] = addCommand
            return self.merge_include_file(path, allCommand)
        else:
            return allCommand

    def get_rpm(self):
        rpm_dict = {}
        for key, values in self.libraries_dict.items():
            keyrpm = set()
            for value in values:
                if ' ' in value:
                    value = value.split(' ')[0]
                # print(value)
                keyrpm.update(search(value))
            if keyrpm:
                rpm_dict[key] = keyrpm
        return self.set_style(rpm_dict)

    def set_style(self, libs_dict):
        for key in libs_dict:
            libs_dict[key] = list(libs_dict[key])
        return libs_dict

    #NOTE：由上面的实现改为下面，去除depends中包含没有可选值的变量的条目，可能会降低覆盖率

    # def set_style(self, libs_dict):
    #     tmp_dict = libs_dict.copy()
    #     lib_var_string = ' '.join(self.lib_var_value.keys())
    #     pattern = r'\$\{([^}]+)\}'
    #     for key, value in tmp_dict.items():
    #         put_v = []
    #         for v in value:
    #             put_in = True
    #             matches = re.findall(pattern, v)
    #             if len(matches) > 0:
    #                 for m in matches:
    #                     if m not in lib_var_string:
    #                         put_in = False
    #                         break
    #             if put_in:
    #                 put_v.append(v)
    #         if put_v:
    #             libs_dict[key] = put_v
    #         else:
    #             libs_dict.pop(key)
    #     return libs_dict

    def lib_var_style(self, lib_vars):
        result = {}
        all_libs = ''
        for key, value in self.libraries_dict.items():
            all_libs += ' '.join(value)

        for name, condition in lib_vars.items():
            if name not in all_libs:
                continue
            new_condition = {}
            for con, value in condition.items():
                new_value = set()
                for v in value:
                    v = v[1:-1] if v[0] == '"' and v[-1] == '"' else v
                    new_value.add(v)
                new_condition[con] = list(new_value)
            result[name] = new_condition
        return result

    def option_con(self, condition, option_name):
        condition = re.sub(r'\+(\w+)_FOUND', lambda m: f'"{m.group(1).lower()}" in pkg.buildRequires', condition)
        condition = re.sub(r'-(\w+)_FOUND', lambda m: f'"{m.group(1).lower()}" not in pkg.buildRequires', condition)
        condition = re.sub(f' when \+\(NOT DEFINED \${{{option_name}}}\)', '', condition, flags=re.IGNORECASE)
        return condition

    def final_option(self):
        final = {}
        for key, values in self.option_dict.items():
            this_key = key[key.find('.') + 1:]
            for value in values:
                final_key = this_key
                condition = 'defineCMakeFlags'
                if 'condition' in value:
                    condition += self.option_con(' ' + value['condition'], this_key)
                    value.pop('condition')
                if key.startswith('option.'):
                    if value['default_value'].lower() == 'on':
                        final_key = '+' + final_key
                    elif value['default_value'].lower() == 'off':
                        final_key = '-' + final_key
                    condition = self.option_condition_process(condition)
                    if condition:
                        final.setdefault(condition, {})[final_key] = value['help_text']
                elif key.startswith('set.'):
                    condition = self.option_condition_process(condition)
                    if condition:
                        final.setdefault(condition, {})[final_key] = value
                else:
                    condition = self.option_condition_process(condition)
                    if condition:
                        final.setdefault(condition, {})[key] = value
        return final

    def save_cmake(self, dir, VAR_MAP = None, write_enable = True):
        if VAR_MAP is None:
            VAR_MAP = {}
        self.set_style(self.libraries_dict)
        yml = yaml.YAML()
        # yml.indent(offset=4)
        yml.width = 4096
        # print(self.libraries_dict)
        # print(self.option_dict)
        fn = os.path.join(dir, "depends.yaml")
        self.libraries_dict.update(self.lib_var_style(self.lib_var_value))
        extract_variables_and_update_var_map(self.lib_var_value, VAR_MAP)
        self.libraries_dict = replace_variables(self.libraries_dict, VAR_MAP)
        if write_enable:
            with open(fn, 'w', encoding='utf-8') as file:
                yml.dump(self.libraries_dict, file)
            option_yml = os.path.join(dir, "options.yaml")
            with open(option_yml, 'w', encoding='utf-8') as file:
                print(f"options:{self.option_dict}")
                yml.dump(self.option_dict, file)
            # rpm_yml = os.path.join(dir, "rpms.yaml")
            # with open(rpm_yml, 'w') as file:
            #     yml.dump(get_rpm(), file)
            command_yml = os.path.join(dir, "commands.yaml")
            with open(command_yml, 'w', encoding='utf-8') as file:
                yml.dump(self.commands_info, file)
            final_option_yml = os.path.join(dir, "final_options.yaml")
            with open(final_option_yml, 'w', encoding='utf-8') as file:
                yml.dump(self.final_option(), file)
            option_set_yml = os.path.join(dir, "option_set.yaml")
            with open(option_set_yml, 'w', encoding='utf-8') as file:
                yml.dump(self.option_condition, file)
            target_yml = os.path.join(dir, "target.yaml")
            with open(target_yml, 'w', encoding='utf-8') as file:
                yml.dump(self.target_condition, file)

        # print(self.option_dict)
        return self.libraries_dict, self.option_dict, self.commands_info, self.final_option(), self.option_condition, self.target_condition

    def save_only_depends(self, dir, VAR_MAP, depends_file_name):
        self.set_style(self.libraries_dict)
        yml = yaml.YAML()
        yml.width = 4096
        fn = os.path.join(dir, depends_file_name)
        # TODO: 做一个字符串替换，如将变量KF_MAJOR_VERSION替换为5、6

        # print(self.libraries_dict)
        extract_variables_and_update_var_map(self.lib_var_value, VAR_MAP)
        self.libraries_dict = replace_variables(self.libraries_dict, VAR_MAP)
        # print(self.libraries_dict)
        # print(VAR_MAP)
        with open(fn, 'w', encoding='utf-8') as file:
            yml.dump(self.libraries_dict, file)
        return self.libraries_dict


def extract_variables_and_update_var_map(input_dict, var_map):
    """
    提取字典中的每一项为变量并更新到 var_map 中
    """
    for key, conditions in input_dict.items():
        # 提取条件中的值并去重
        # conditions.values() 是一个list[{var1-1,var1-2},{var2-1,var2-2}]
        all_valued = set()
        for condition_vars in conditions.values():
            all_valued.update(condition_vars)
        values = list(all_valued)
        var_map[key] = values


def replace_variables(mapping_dict, var_map):
    """
    使用 VAR_MAP 中的值替换映射字典中的变量
    """
    replaced_dict = {}

    for key, values in mapping_dict.items():
        replaced_values = []
        for value in values:
            replaced_values.extend(expand_value(value, var_map))
        replaced_dict[key] = replaced_values

    return replaced_dict


def remove_extra_braces(value):
    """
    移除字符串中的多余大括号，只保留一对大括号
    同时删去"pkg.var."
    """
    pattern = re.compile(r'(\$\{[^{}]+\})|(\$\{\{[^{}]+\}\})')  # 匹配单层和双层大括号
    while True:
        new_value = pattern.sub(
            lambda m: m.group(1) if m.group(1) else m.group(2).replace('{{', '{').replace('}}', '}'), value)
        if new_value == value:
            break
        value = new_value
    value = value.replace("pkg.var.", '')
    return value


def expand_value(value, var_map):
    """
    对单个值进行变量替换，并返回所有可能的替换结果
    """
    value = remove_extra_braces(value)
    pattern = re.compile(r'\$\{([^{}]+)\}')  # 匹配单层大括号
    matches = pattern.findall(value)

    if not matches:
        return [value]

    expanded_values = [value]

    for match in matches:
        if match in var_map:
            temp_values = []
            for exp_value in expanded_values:
                for var_value in var_map[match]:
                    temp_values.append(exp_value.replace(f"${{{match}}}", str(var_value)))
            expanded_values = temp_values

    return expanded_values


# local_path = r'C:\Users\admin\Desktop\dependency-analysis\spec-cmake'
# for entry in os.listdir(local_path):
#     full_path = os.path.join(local_path, entry)
#     if os.path.isdir(full_path):
#         cmake = CmakeDepends()
#         file_path = os.path.join(full_path, r"CMakeLists.txt")
#         cmake.parse(file_path)
#         cmake.save_cmake(full_path)


def debug(special_case_dir):
    """
        针对 special_case_dir 下的存在问题的所有文件，进行分析
    """
    analysis_results = {}

    for root, dirs, files in os.walk(special_case_dir):
        for file in files:
            _, extention = os.path.splitext(file)
            if extention == '.txt' or extention == '.cmake':
                file_path = os.path.join(root, file)
                cmake = CmakeDepends()
                cmake.parse(file_path)
                VAR_MAP = {'QT_MAJOR_VERSION': ['5', '6']}
                # cmake.save_cmake("D:\Iron\Work\解析有问题的cmake")
                cmake.save_only_depends(root, VAR_MAP, f"{file}_depends.yaml")






# if __name__ == '__main__':
#     debug("D:\Iron\Work\解析有问题的cmake")
#     local_path = r'spec-test'
#     for entry in os.listdir(local_path):
#         full_path = os.path.join(local_path, entry)
#         if os.path.isdir(full_path):
#             cmake = CmakeDepends()
#             file_path = os.path.join(full_path, r"CMakeLists.txt")
#             cmake.parse(file_path)
#             cmake.save_cmake(full_path)

# cmake = CmakeDepends()

# file_path = os.path.join(r'C:\Users\admin\Desktop\dependency-analysis\spec-cmake\usb-sd-creator', r"CMakeLists.txt")
# file_path = os.path.join(r'/home/elpsy/workspace/sow/Test/libmetal/libmetal-2022.10.0/cmake', r"options.cmake")
# cmake.parse(file_path)
# cmake.save_cmake(r'/home/elpsy/workspace/sow')
